package com.hsource.paymentcenter.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.hsource.common.core.domain.message.MessageVO;
import com.hsource.common.utils.RedisTopicUtil;
import com.hsource.paymentcenter.conf.ali.AliPayConfig;
import com.hsource.paymentcenter.conf.redis.RedisMessageProducer;
import com.hsource.paymentcenter.domain.order.Order;
import com.hsource.paymentcenter.domain.pay.Refund;
import com.hsource.paymentcenter.util.SpringUtils;
import com.hsource.paymentcenter.util.StringUtils;
import com.hsource.paymentcenter.util.redis.RedisKeyUtil;
import com.hsource.paymentcenter.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author yangYang
 * @version 1.0
 * @date 2020/10/15 11:29
 * @describe 阿里支付宝流程
 */
@Slf4j
public class AliPayServiceImpl {


    /**
     * 支付宝退款
     * @param refund
     * @return
     */
    public static boolean refund(Refund refund){
        AliPayConfig config = SpringUtils.getBean(AliPayConfig.class);
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(config.getGatewayUrl(), config.getAppId(), config.getPrivateKey(), config.getFormat(), config.getCharset(), config.getAliPublicKey(), config.getSignType());
            //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.refund
            AlipayTradeRefundRequest alipayTradeRefundRequest = new AlipayTradeRefundRequest();
            //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            if(StringUtils.isNotBlank(refund.getTransaction_id())) {
                model.setTradeNo(refund.getTransaction_id());
            }else{
                model.setTradeNo(refund.getOut_trade_no());
            }
            model.setRefundReason(StringUtils.isNotBlank(refund.getRefund_desc())?refund.getRefund_desc():"退款");
            model.setRefundAmount(refund.getRefund_fee());
//            model.setRefundAmount("0.01");
            alipayTradeRefundRequest.setBizModel(model);
            AlipayTradeRefundResponse response = alipayClient.execute(alipayTradeRefundRequest);
            log.warn("===========AliPayServiceImpl-refund==============="+JSONObject.toJSONString(response));
            return response.isSuccess();
        }catch (AlipayApiException e) {
            log.error("【支付宝支付 -- 退款失败】原因为:{}",e.getMessage());
            return false ;
        }
    }
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            log.info("支付宝=="+name+"&值==="+values[0]);
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }
    /**
     * 支付通知回调
     * @param request 请求体
     * @param payType 支付类型
     */
    public void payNotify(String payType,HttpServletRequest request)  {
        AliPayConfig config = SpringUtils.getBean(AliPayConfig.class);
        RedisMessageProducer redisMessageProducer = SpringUtils.getBean(RedisMessageProducer.class);
        Map<String, String> stringStringMap =convertRequestParamsToMap(request);
        try {
            boolean flag = AlipaySignature.rsaCheckV1(stringStringMap, config.getAliPublicKey(), config.getCharset(), config.getSignType());
            if (true) {
                if ("TRADE_SUCCESS".equals(stringStringMap.get("trade_status"))) {
                    if (stringStringMap.size() > 0) {
                        stringStringMap.put("orderPayType", payType);
                        stringStringMap.put("return_code", "SUCCESS");
                        String messageId = "" + System.currentTimeMillis();
                        MessageVO m = new MessageVO();
                        m.setMessageId(messageId);
                        m.setTopic(RedisTopicUtil.TOPIC_ORDER_CENTER);
                        m.setData(stringStringMap);
                        redisMessageProducer.sendMessage(RedisTopicUtil.TOPIC_ORDER_CENTER, m);
                    }
                }else{
                    stringStringMap.put("return_code","ERROR");
                }
            }
        }catch (AlipayApiException e) {
            log.error("【支付宝支付--异步回调】回调失败,阿里云接口调用错误,原因为:{}",e.getMessage());
        } catch (Exception e) {
            log.error("【支付宝支付--异步回调】回调失败,原因为:{}",e.getMessage());
        }

    }

    /**
     * 去支付统一下单
     * @param orderId
     * @param request
     */
    public String toOrderPay(String orderId, HttpServletRequest request) throws Exception {
        JSONObject returnValue = null;
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        AliPayConfig config = SpringUtils.getBean(AliPayConfig.class);
        Map<String, String> resp =null;


        String orderKeyString = RedisKeyUtil.getRedisKeyString(orderId, RedisKeyUtil.ORDER_LIST_STRING);
        if(redisUtil.hasKey(orderKeyString)) {
            AlipayClient alipayClient = new DefaultAlipayClient(config.getGatewayUrl(), config.getAppId(), config.getPrivateKey(), config.getFormat(), config.getCharset(), config.getAliPublicKey(), config.getSignType());
            AlipayTradeAppPayRequest alipayTradeAppPayRequest = new AlipayTradeAppPayRequest();

            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            redisUtil.get(orderKeyString).toString();
            Order order = JSONObject.parseObject(redisUtil.get(orderKeyString).toString(), Order.class);
            model.setBody("本草元堂");
            model.setSubject("在线询医");
            model.setOutTradeNo(order.getId());
            model.setTimeoutExpress("30m");
            model.setTotalAmount(String.valueOf(order.getPrice()));
//            model.setTotalAmount("0.01");
            model.setProductCode("QUICK_MSECURITY_PAY");
            alipayTradeAppPayRequest.setBizModel(model);
            alipayTradeAppPayRequest.setNotifyUrl(config.getNotifyUrl());
            try {
                //这里和普通的接口调用不同，使用的是sdkExecute
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(alipayTradeAppPayRequest);
                //就是orderString 可以直接给客户端请求，无需再做处理。
                String bodyString = response.getBody();
                redisUtil.expire(orderKeyString,3600);
                return bodyString;
            } catch (AlipayApiException e) {
                System.out.println(e.getErrMsg().toString());
            }

        }
        return null;
    }
}
